﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;

namespace DeVierKoeden.Dynamicweb.CreateSite.DataAnonymization
{
  internal class DataAnonymizer
  {
    private readonly IAnonymizeSettings _settings;
    private readonly ILogger _progresLogger;

    /// <summary>
    /// Initializes a new instance of the <see cref="DataAnonymizer"/> class.
    /// </summary>
    internal DataAnonymizer(IAnonymizeSettings settings, ILogger progresLogger)
    {
      _settings = settings;
      _progresLogger = progresLogger;
    }

    internal void AnonymizeData()
    {
      const string sqlFormat = "SELECT DISTINCT {0} FROM {1} WHERE {0} IS NOT NULL AND {0} <> ''";
      var tables = GetTablesThatNeedReplacement(_settings.AnonymizationMethod);

      using (var readConnection = new SqlConnection(_settings.BuildConnectionString()))
      {
        readConnection.Open();
        using (var writeConnection = new SqlConnection(_settings.BuildConnectionString()))
        {
          writeConnection.Open();
          foreach (var tableInfo in tables)
          {
            _progresLogger.LogProgress("Anonymizing " + tableInfo.TableName);
            foreach (var column in tableInfo.Columns)
            {
              if (column.ReplacementBehavior == ReplacementBehavior.Suffix)
              {
                try
                {
                  string updateSql = $"UPDATE {tableInfo.TableName} SET {column.ColumnName} = {column.ColumnName} + '.{_settings.AnonymizationSuffix}' WHERE {column.ColumnName} IS NOT NULL AND {column.ColumnName} <> ''";
                  using (var updateCommand = new SqlCommand(updateSql, readConnection))
                  {
                    updateCommand.ExecuteNonQuery();
                  }
                }
                catch 
                {
                  // TODO Failed to update password; maybe had a quote in it or so.
                }
              }
              else
              {
                var sql = string.Format(sqlFormat, column.ColumnName, tableInfo.TableName);
                using (var command = new SqlCommand(sql, readConnection))
                {
                  using (var reader = command.ExecuteReader())
                  {
                    if (reader.HasRows)
                    {
                      while (reader.Read())
                      {
                        try
                        {
                          string emailOld = reader.GetString(0);
                          string emailNew = column.ReplacementBehavior == ReplacementBehavior.Random ? Guid.NewGuid() + "@dynamicwebusa.com" : string.Format("{0}.{1}", emailOld, _settings.AnonymizationSuffix);
                          const string sqlUpdateFormat = "UPDATE {0} SET {1} = '{2}' WHERE {1} = '{3}'";
                          string sqlUpdate = string.Format(sqlUpdateFormat, tableInfo.TableName, column.ColumnName, emailNew, emailOld);
                          using (var command2 = new SqlCommand(sqlUpdate, writeConnection))
                          {
                            command2.ExecuteNonQuery();
                          }
                        }
                        catch 
                        {
                          // TODO Failed to update password; maybe had a quote in it or so.
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

    private List<AnonymizeDataTableInfo> GetTablesThatNeedReplacement(ReplacementBehavior replacementBehavior)
    {
      return new List<AnonymizeDataTableInfo>
      {
        new AnonymizeDataTableInfo
        {
          TableName = "AccessUser", Columns = new List<AnonymizeDataColumnInfo>
          {
            new AnonymizeDataColumnInfo {ColumnName = "AccessUserEmail", ReplacementBehavior = replacementBehavior}
          }
        },
        new AnonymizeDataTableInfo
        {
          TableName = "AccessUserAddress", Columns = new List<AnonymizeDataColumnInfo>
          {
            new AnonymizeDataColumnInfo {ColumnName = "AccessUserAddressEmail", ReplacementBehavior = replacementBehavior}
          }
        },
        new AnonymizeDataTableInfo
        {
          TableName = "EcomOrders", Columns = new List<AnonymizeDataColumnInfo>
          {
            new AnonymizeDataColumnInfo {ColumnName = "OrderReSendEmail", ReplacementBehavior = replacementBehavior},
            new AnonymizeDataColumnInfo {ColumnName = "OrderCustomerEmail", ReplacementBehavior = replacementBehavior},
            new AnonymizeDataColumnInfo {ColumnName = "OrderDeliveryEmail", ReplacementBehavior = replacementBehavior}
          }
        },
        new AnonymizeDataTableInfo
        {
          TableName = "EcomRmas", Columns = new List<AnonymizeDataColumnInfo>
          {
            new AnonymizeDataColumnInfo {ColumnName = "RmaCustomerEmail", ReplacementBehavior = replacementBehavior},
            new AnonymizeDataColumnInfo {ColumnName = "RmaDeliveryEmail", ReplacementBehavior = replacementBehavior}
          }
        },
        new AnonymizeDataTableInfo
        {
          TableName = "ForumMessage", Columns = new List<AnonymizeDataColumnInfo>
          {
            new AnonymizeDataColumnInfo {ColumnName = "ForumMessageAuthorEMail", ReplacementBehavior = replacementBehavior}
          }
        },
        new AnonymizeDataTableInfo
        {
          TableName = "Comment", Columns = new List<AnonymizeDataColumnInfo>
          {
            new AnonymizeDataColumnInfo {ColumnName = "CommentEmail", ReplacementBehavior = replacementBehavior}
          }
        },
      };
    }
  }
}
